#ifndef __M_TP_H__
#define __M_TP_H__
#include <iostream>
#include <queue>
#include <pthread.h>

#define MAX_PTHREAD 5

typedef bool (*handler_t)(int);

class ThreadTask
{
private:
    int _data;
    handler_t _handler;
public:
    ThreadTask():_data(-1),_handler(NULL){}
    ThreadTask(int data, handler_t handler)
    {
        _data = data;
        _handler = handler;
    }
    void Settask(int data, handler_t handler)
    {
        _data = data;
        _handler = handler;
    }
    void run()
    {
        _handler(_data);
    }
};

class ThreadPool
{
private:
    bool _tp_quit;
    pthread_cond_t _cond;
    pthread_mutex_t _lock;
    int pthread_max;
    int pthread_cur;
    std::queue<ThreadTask*> _Taskqueue;
private:
    void Lockqueue()
    {
        pthread_mutex_lock(&_lock);
    }
    void UnLockqueue()
    {
        pthread_mutex_unlock(&_lock);
    }
    void Wakeone()
    {
        pthread_cond_signal(&_cond);
    }
    void Wakeall()
    {
        pthread_cond_broadcast(&_cond);
    }
    void Threadquit()
    {
        pthread_cur--;
        UnLockqueue();
        pthread_exit(NULL);
    }
    void Threadwait()
    {
        if(_tp_quit){
            Threadquit();
        }
        pthread_cond_wait(&_cond,  &_lock);
    }
    bool Isempty()
    {
        return _Taskqueue.empty();
    }
    static void *thr_start(void *arg)
    {
        ThreadPool *tp = (ThreadPool*) arg;
        while(1)
        {
            tp->Lockqueue();
            while(tp->Isempty())
            {
                tp->Threadwait();
            }
            ThreadTask *tt;
            tp->PopTask(&tt);
            tp->UnLockqueue();
            tt->run();
            delete tt;
        }
        return NULL;
    }
public:
    ThreadPool(int max = MAX_PTHREAD):pthread_max(max),pthread_cur(max),_tp_quit(false)
    {
        pthread_cond_init(&_cond, NULL);
        pthread_mutex_init(&_lock, NULL);
    }
    ~ThreadPool()
    {
        pthread_cond_destroy(&_cond);
        pthread_mutex_destroy(&_lock);
    }
    bool initPool()
    {
        pthread_t pid;
        for(int i = 0; i < pthread_max; i++)
        {
            int ret = pthread_create(&pid, NULL, thr_start, this);
            if(ret != 0)
            {
                std::cout << "create pool thread fail\n";
                return false;
            }
        }
        return true;
    }
    bool PushTask(ThreadTask *tt)
    {
        Lockqueue();
        if(_tp_quit){
            UnLockqueue();
            return false;
        }
        _Taskqueue.push(tt);
        Wakeone();
        UnLockqueue();
        return true;
    }
    bool PopTask(ThreadTask **tt) {
        *tt = _Taskqueue.front();
        _Taskqueue.pop();
        return true;
    }
    bool Poolquit()
    {
        Lockqueue();
        _tp_quit = true;
        UnLockqueue();
        while(pthread_cur)
        {
            Wakeall();
            usleep(1000);
        }
        return true;
    }

};
#endif

